<?php
/**
 * CString class file.
 * 字符串处理类.
 * @author Huan Song <iphper@yeah.net>
 * @version $Id: CString.php 1 2011-02-10 16:51:00Z huan.song $
 * @package system.helpers
 * @since 2.0
 */
class CString
{
	/**
	 * 转换字符串编码.
	 * @param string $str 需要转换的字符串.
	 * @param string $out_charset 转换后的编码.
	 * @return string 转换后的字符串.
	 */
	public static function convertEncoding($str, $out_charset = null)
	{
		if (null === $out_charset)
			$out_charset = CViewConfig::getCharset();
		
		$in_charset = mb_detect_encoding($str, 'GBK, UTF-8, GB2312, ASCII');
		return mb_convert_encoding($str, $out_charset, $in_charset);
	}
	
	/**
	 * 弹出消息框，并跳转到指定链接, 如果链接为空, 跳转到前一个链接.
	 * @param string $msg 需要弹出的消息.
	 * @param string $url 跳转的链接地址.
	 * @return void
	 */
	public static function alertMsg($msg = null, $url = null)
	{
		$url = (null === $url) ? 'history.go(-1);' : "window.location.href = '$url'";
		$html  = "<meta http-equiv='content-Type' content='text/html; charset=utf-8' />\r\n";
		$html .= "<script language='javascript' type='text/javascript'>\r\n";
		if (null !== $msg)
			$html .= "alert('$msg');\r\n";

		$html .= "location: $url\r\n";
		$html .= '</script>';
		exit($html);
	}
	
	/**
	 * 随机字符串.
	 * @param integer $len 随机取的字符串的长度.
	 * @param string $format: ALL(英文字母加数字),LETTER(字母),NUMBER(数字)
	 * @return string 随机字符串.
	 */
	public static function randStr($len = 4, $format = 'ALL') 
	{
		$chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; 
		$start = $format=='NUMBER' ? 52 : 0;
		$end = $format=='LATTER' ? 51 : 61;
		$str = '';
		for ($i=0; $i<$len; $i++)
			$str .= $chars{mt_rand($start, $end)};
		
		return $str;
	}

	/**
	 * GBK编码字符双字节截串，一个汉字占一个字符.
	 * @param string $str.
	 * @param integer $start.
	 * @param integer $length.
	 * @return string 截取后的字符串.
	 */
	public static function gbkDSubstr($str, $start = 0, $length = -1) 
	{
		$substr = '';
		$str = str_replace(array('&amp;', '&quot;', '&lt;', '&gt;', '&nbsp;'), 
						   array('&', '"', '<', '>', ' '), $str);
		$strlen = strlen($str);
		for ($i=0; $i<$strlen; $i++) 
		{
			if (ord($str[$i]) > 128) 
				$str_split[] = $str[$i].$str[++$i];
			else 
				$str_split[] = $str[$i];
		}
		
		$count = count($str_split);
		$sublen = $count - $start;
		if ($sublen > 0) 
		{
			$length = $length < 0 ? $sublen : $length;
			$cutpoint = $length < $sublen ? $start + $length : $start + $sublen;
			for ($i=$start; $i<$cutpoint; $i++) 
				$substr .= $str_split[$i];
				
		}
		$substr = str_replace(array('&', '"', '<', '>', ' '), 
							  array('&amp;', '&quot;', '&lt;', '&gt;', '&nbsp;'), $substr);
		return $substr;
	}

	/**
	 * GBK编码字符单字节截串，一个汉字占两个字符.
	 * @param string $str.
	 * @param integer $start.
	 * @param integer $length.
	 * @return string 截取后的字符串.
	 */
	public static function gbkSSubstr($str, $start = 0, $length = -1) {
		$substr = '';
		$str = str_replace(array('&amp;', '&quot;', '&lt;', '&gt;', '&nbsp;'), 
						   array('&', '"', '<', '>', ' '), $str);
		$strlen = strlen($str);
		if ($strlen > 0) 
		{
			$end = $length < 0 || ($start + $length) > $strlen? $strlen : $start + $length;
			$c = '';
			for ($i=0; $i<=$strlen; $i++) 
			{
				if ($start==0 || $i>$start) 
					$substr .= $c;
					
				if (ord($str[$i]) > 128) 
					$c = $str[$i].$str[++$i];
				else 
					$c = $str[$i];
					
				if ($i>=$end) 
					break;
			}
		}
		$substr = str_replace(array('&', '"', '<', '>', ' '), 
							  array('&amp;', '&quot;', '&lt;', '&gt;', '&nbsp;'), $substr);
		return $substr;
	}

	/**
	 * UTF-8编码字符双字节截串，一个汉字占一个字符.
	 * @param string $str.
	 * @param integer $start.
	 * @param integer $length.
	 * @return string 截取后的字符串.
	 */
	public static function utf8DSubstr($str, $start = 0, $length = -1) 
	{
		if ($length === -1)
			$length = strlen($str);
			
		return preg_replace('#^(?:[\x00-\x7F]|[\xC0-\xFF][\x80-\xBF]+){0,' . $start . '}'.
		'((?:[\x00-\x7F]|[\xC0-\xFF][\x80-\xBF]+){0,' . $length . '}).*#s',
		'$1', $str);
	}

	/**
	 * UTF-8编码字符单字节截串，一个汉字占两个字符.
	 * @param string $str.
	 * @param int $start.
	 * @param int $length.
	 * @return string 截取后的字符串.
	 */
	public static function utf8SSubstr($str, $start = 0, $length = -1) 
	{
		$str = str_replace(array('&amp;', '&quot;', '&lt;', '&gt;'), 
						   array('&', '"', '<', '>'), $str);
		
		$strlen = strlen($str);
		if ($length === -1) $length = $strlen;
		$end = $start + $length;
		if ($start === 0) $end++;
		$n = $tn = $noc = 0;
		$b = true;
		while ($n < $strlen) 
		{
			$t = ord($str[$n]);
			if ($t == 9 || $t == 10 || (32 <= $t && $t <= 126)) {
				$tn = 1; $n++; $noc++;
			}
			else if (194 <= $t && $t <= 223) { 
				$tn = 2; $n += 2; $noc += 2;
			}
			else if (224 <= $t && $t <= 239) { 
				$tn = 3; $n += 3; $noc += 2;
			}
			else if (240 <= $t && $t <= 247) { 
				$tn = 4; $n += 4; $noc += 2;
			}
			else if (248 <= $t && $t <= 251) { 
				$tn = 5; $n += 5; $noc += 2;
			}
			else if ($t == 252 || $t == 253) { 
				$tn = 6; $n += 6; $noc += 2;
			}
			else 
				$n++;
			
			if ($b && $noc >= $start) 
			{
				if ($noc === $start)
					$start = $n;
				else 
				{
					$start = $n - $tn;
					$end--;
				}
				$b = false;
			}
			
			if ($noc >= $end) break;
		}
		if ($noc > $end) $n -= $tn;
		
		$substr = substr($str, $start, $n-$start);
		$substr = str_replace(array('&', '"', '<', '>'), 
							  array('&amp;', '&quot;', '&lt;', '&gt;'), $substr);
		return $substr;
	}

	/**
	 * 过滤表单提交的数据.
	 * @param string $str.
	 * @return string 过滤后的字符串.
	 */
	public static function sanitize($str)
    {
        $ret = preg_replace("/[\r\n]+/", ' ', $str);
		return htmlspecialchars(trim($ret));
    }

    /**
     * 转义字符串或数组.
     * @param string|array $param.
     * @return string|array 转义后的字符串或者数组.
     */
	public static function addslashes($param) 
	{
		if (is_array($param)) 
		{
			foreach ($param as $key => $val) 
				$param[$key] = self::addslashes($val);
		} 
		else 
			$param = addslashes($param);
			
		return $param;
	}
}
